import {
	ref
} from 'vue'
import {
	haversine,
	smoothPoint,
	isSpeedValid
} from '@/utils/geo'

export function useTracker() {
	const isRunning = ref(false)
	const isPaused = ref(false)
	const pointsRaw = ref([])
	const pointsSmooth = ref([])
	const totalDist = ref(0)
	const startTime = ref(0)
	const lastTs = ref(0)
	const pauseOffset = ref(0)
	const pauseStart = ref(0)

	function elapsedMs() {
		if (!startTime.value) return 0
		const now = Date.now()
		const pausedNow = isPaused.value ? (now - pauseStart.value) : 0
		return now - startTime.value - pauseOffset.value - pausedNow
	}

	async function start() {
		try {
			await uni.authorize({
				scope: 'scope.userLocation'
			})
		} catch (e) {
			await uni.showModal({
				title: '需要定位权限',
				content: '请在设置中开启定位权限以记录轨迹',
				success: r => {
					if (r.confirm) uni.openSetting({})
				}
			})
			return
		}
		isRunning.value = true;
		isPaused.value = false
		pointsRaw.value = [];
		pointsSmooth.value = []
		totalDist.value = 0;
		startTime.value = Date.now()
		lastTs.value = 0;
		pauseOffset.value = 0;
		pauseStart.value = 0

		// #ifdef MP-WEIXIN
		const startFn = uni.startLocationUpdateBackground || uni.startLocationUpdate
		startFn({
			success: () => {
				uni.onLocationChange(handleLoc)
			},
			fail: () => {
				uni.showToast({
					title: '定位启动失败',
					icon: 'none'
				})
			}
		})
		// #endif
	}

	function pause() {
		if (!isRunning.value || isPaused.value) return
		isPaused.value = true
		pauseStart.value = Date.now()
	}

	function resume() {
		if (!isRunning.value || !isPaused.value) return
		isPaused.value = false
		pauseOffset.value += Date.now() - pauseStart.value
		pauseStart.value = 0
	}

	function stop() {
		isRunning.value = false;
		isPaused.value = false
		// #ifdef MP-WEIXIN
		try {
			uni.offLocationChange(handleLoc)
		} catch (e) {}
		try {
			uni.stopLocationUpdate({})
		} catch (e) {}
		// #endif
		return snapshot()
	}

	function snapshot() {
		return {
			points: pointsSmooth.value,
			rawPoints: pointsRaw.value,
			distance: totalDist.value,
			duration: elapsedMs(),
			startedAt: startTime.value,
			endedAt: Date.now()
		}
	}

	function handleLoc(loc) {
		if (!isRunning.value || isPaused.value) return
		const curr = {
			latitude: loc.latitude,
			longitude: loc.longitude
		}
		const ts = Date.now()
		const prevS = pointsSmooth.value[pointsSmooth.value.length - 1]
		const prevRaw = pointsRaw.value[pointsRaw.value.length - 1]
		if (prevRaw && !isSpeedValid(prevRaw, curr, lastTs.value, ts, 6)) {
			lastTs.value = ts;
			return
		}
		const smoothed = smoothPoint(prevS, curr, 0.2)
		if (prevS) totalDist.value += haversine(prevS, smoothed)
		pointsRaw.value.push({
			...curr,
			ts,
			spd: loc.speed,
			acc: loc.accuracy
		})
		pointsSmooth.value.push(smoothed)
		lastTs.value = ts
	}

	return {
		isRunning,
		isPaused,
		pointsSmooth,
		totalDist,
		elapsedMs,
		start,
		pause,
		resume,
		stop,
		snapshot
	}
}